#include "../pch.h"

#include "CharUnicodeInfo.h"

namespace BFX
{

//////////////////////////////////////////////////////////////////////////////

REFDecoderFallbackBuffer::REFDecoderFallbackBuffer()
	: m_pByteStart(NULL), m_pCharEnd(NULL)
{
}

REFDecoderFallbackBuffer::~REFDecoderFallbackBuffer()
{
}

bool REFDecoderFallbackBuffer::Fallback(SequenceT<BYTE> bytesUnknown, const BYTE* pBytes, INOUT UCHAR*& pChars)
{
	BFX_ASSERT1(m_pByteStart != NULL, "Fallback without calling Initialize");

	// See if there's a fallback character and we have an output buffer then copy our string.
	if (Fallback(bytesUnknown, (int)(pBytes - m_pByteStart - bytesUnknown.GetSize())))
	{
		UCHAR ch;
		UCHAR* pCharTemp = pChars;
		bool bHighSurrogate = false;
		while ((ch = GetNextChar()) != 0)
		{
			// Make sure no mixed up surrogates
			if (CharUnicodeInfo::IsSurrogate(ch))
			{
				if (CharUnicodeInfo::IsHighSurrogate(ch))
				{
					// High Surrogate
					BFX_ENSURE1(!bHighSurrogate, "String contains invalid Unicode code points.");
					bHighSurrogate = true;
				}
				else
				{
					// Low surrogate
					BFX_ENSURE1(bHighSurrogate, "String contains invalid Unicode code points.");
					bHighSurrogate = false;
				}
			}

			if (pCharTemp >= m_pCharEnd)
			{
				// No buffer space
				return false;
			}

			*(pCharTemp++) = ch;
		}

		// Need to make sure that bHighSurrogate isn't true
		BFX_ENSURE1(!bHighSurrogate, "String contains invalid Unicode code points.");

		// Now we aren't going to be false, so its OK to update chars
		pChars = pCharTemp;
	}

	return true;
}

// This version just counts the fallback and doesn't actually copy anything.
int REFDecoderFallbackBuffer::Fallback(SequenceT<BYTE> bytesUnknown, const BYTE* pBytes)
{
	BFX_ASSERT1(m_pByteStart != NULL, "Used Fallback without calling Initialize");

	// See if there's a fallback character and we have an output buffer then copy our string.
	if (Fallback(bytesUnknown, (int)(pBytes - m_pByteStart - bytesUnknown.GetSize())))
	{
		int nCount = 0;

		UCHAR ch;
		bool bHighSurrogate = false;
		while ((ch = GetNextChar()) != 0)
		{
			// Make sure no mixed up surrogates
			if (CharUnicodeInfo::IsSurrogate(ch))
			{
				if (CharUnicodeInfo::IsHighSurrogate(ch))
				{
					// High Surrogate
					BFX_ENSURE1(!bHighSurrogate, "String contains invalid Unicode code points.");
					bHighSurrogate = true;
				}
				else
				{
					// Low surrogate
					BFX_ENSURE1(bHighSurrogate, "String contains invalid Unicode code points.");
					bHighSurrogate = false;
				}
			}

			nCount++;
		}

		// Need to make sure that bHighSurrogate isn't true
		BFX_ENSURE1(!bHighSurrogate, "String contains invalid Unicode code points.");

		return nCount;
	}

	// If no fallback return 0
	return 0;
}

//////////////////////////////////////////////////////////////////////////////

REFDecoderFallback::REFDecoderFallback()
{
}


REFDecoderFallback::~REFDecoderFallback()
{
}

}	//	namespace BFX
